﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BDShop.Business;
using BDShop.Business.Cache;
using BDShop.Entities;
using BDShop.Configuration;
using BDShop.Models;
using BDShop.Utilities.Managers;
using BDShop.Framework.Web;
using WebMatrix.WebData;
using BDShop.Filters;
using Recaptcha;
using BDShop.Resources;
using PagedList;
using BDShop.Framework.Utility;

namespace BDShop.Controllers
{
    [InitializeSimpleMembership]
    public class ProductController : Controller
    {

        public ActionResult Index(long id)
        {
            //update view for product
            ProductService.UpdateView(id);

            ProductModels productModels = new ProductModels();
            //Lay thong tin san pham
            Product product = ProductService.GetProductByID(id);
            productModels.ID = id;

            //Get category of product to set navigate
            string navigate = "";
            string[] categoryDefinition = null;
            if (!string.IsNullOrEmpty(product.CategoryDefinition))
            {
                categoryDefinition = product.CategoryDefinition.Split('|')[0].Split('#');
            }
            navigate += "<a href='/'>Trang chủ</a> » ";
            if (categoryDefinition != null)
            {
                foreach (string cat in categoryDefinition)
                {
                    navigate += "<a href='" + UrlManager.ProductOfCatUrl(int.Parse(cat.Split(':')[0]), cat.Split(':')[1]) + "'>" + cat.Split(':')[1] + "</a>" + " » ";
                }
            }
            navigate += "<span>" + product.Name + "</span>";
            ViewBag.Navigate = navigate;

            //get number comment
            List<ProductComment> lstComment = ProductCommentService.GetByUserID(WebSecurity.CurrentUserId, id);
            ViewBag.NumberComment = lstComment.Count;

            //Get brand of product
            Brand brand = BrandService.GetBrandByID(product.BrandId);
            productModels.Brand = brand.Name;
            productModels.Name = product.Name;
            productModels.Status = (ProductStatus)product.Status;
            productModels.Description = product.Description;
            productModels.Price = product.Price;
            productModels.DiscountPrice = product.DiscountPrice;
            productModels.MarketPrice = product.MarketPrice;
            productModels.Rater = product.Rater;
            productModels.Rating = product.Rating;
            productModels.htmlTitle = product.HtmlTitle;
            productModels.htmlDescription = product.HtmlDescription;
            productModels.htmlKeywords = product.HtmlKeywords;
            //Get property
            List<Constant> lstConstant = ConstantCache.Instance.Get().Where(c => c.Key.ToUpper() == BDShopConfiguration.Key.color.ToUpper()).ToList();
            List<ProductProperty> lstProductProperty = ProductPropertyService.GetByID(id);

            var property = lstConstant.Join(lstProductProperty, c => c.ID, p => p.Property, (c, p) =>
                                                                                                new
                                                                                                {
                                                                                                    c.Value,
                                                                                                    c.Description
                                                                                                });
            List<SelectListItem> lstProductPropertyData = property.Select(i => new SelectListItem()
                                                        {
                                                            Text = i.Description,
                                                            Value = i.Value
                                                        }).ToList();
            lstProductPropertyData.Insert(0, new SelectListItem() { Text = "-- Vui lòng chọn --", Value = "" });
            IEnumerable<SelectListItem> productPropertyData = lstProductPropertyData;
            ViewBag.productPropertyData = productPropertyData;
            //Get product image
            List<ProductImage> lstProductImage = ProductImageService.Get5ByProductID(id);
            ViewBag.ProductImage = lstProductImage;
            ViewBag.FirstProductImage = lstProductImage.First();

            return View(productModels);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult AddToCart(long productID, int quantity, string ddlColor)
        {
            List<OrderDetailModels> lstOrder = new List<OrderDetailModels>();
            lstOrder = SessionHelper.SessionObjects.GetValueOrDefault<List<OrderDetailModels>>("Order");

            //get price of product
            Product product = ProductService.GetProductByID(productID);

            OrderDetailModels order;
            if (lstOrder == null)
            {
                lstOrder = new List<OrderDetailModels>();
                order = new OrderDetailModels(productID, quantity, ddlColor, product.Price);
                lstOrder.Add(order);
            }
            else
            {
                bool flag = true;
                foreach (var ord in lstOrder)
                {
                    if (ord.productID == productID && ord.propertyID == ddlColor)
                    {
                        flag = false;
                        if ((ord.quantity + quantity) < 30)
                        {
                            ord.quantity += quantity;
                        }
                        break;
                    }
                }
                if (flag)
                {
                    order = new OrderDetailModels(productID, quantity, ddlColor, product.Price);
                    lstOrder.Add(order);
                }
            }

            //add product to cart
            if (SessionHelper.SessionObjects.ContainsKey("Order"))
            {
                SessionHelper.SessionObjects["Order"] = lstOrder;
            }
            else
            {
                SessionHelper.SessionObjects.Add("Order", lstOrder);
            }

            return RedirectToRoute("gio-hang");
        }

        public ActionResult AddToWishList(long id)
        {
            if (WebSecurity.IsAuthenticated)
            {
                //add to wish list
                WishList wl = new WishList();
                wl.CustomerID = WebSecurity.CurrentUserId;
                wl.ProductID = id;
                wl.DateCreated = DateTime.Now;
                if (WishListService.Insert(wl))
                {
                    return RedirectToAction("WishList", "Account");
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                return RedirectToRoute("dang-nhap");
            }
        }

        [HttpPost]
        [RecaptchaControlMvc.CaptchaValidator]
        public ActionResult Comment(bool captchaValid, string content, int rating, long productID)
        {
            if (captchaValid)
            {
                //add comment
                ProductComment comment = new ProductComment();
                comment.CustomerID = WebSecurity.CurrentUserId;
                comment.Content = content;
                comment.ProductID = productID;
                comment.Status = (int)CommentStatus.WaittingApprove;
                comment.DateCreated = DateTime.Now;
                if (ProductCommentService.Insert(comment))
                {
                    //update rating for product
                    if (ProductService.Update(productID, rating))
                    {
                        return Json("Đăng bình luận thành công. Vui lòng chờ ban quản trị kiểm duyệt thông tin.");
                    }
                    else
                    {
                        return Json("Có lỗi trong quá trình bình chọn cho cho sản phẩm.");
                    }
                }
                else
                {
                    return Json("Có lỗi trong quá trình đăng bình luận.");
                }
            }
            else
            {
                return Json("Mã xác thực không hợp lệ.");
            }
        }

        public ActionResult CommentList(long id)
        {
            List<ProductCommentModels> lstCommentModels = new List<ProductCommentModels>();
            List<ProductComment> lstComment = ProductCommentService.GetByUserID(WebSecurity.CurrentUserId, id);
            foreach (var productComment in lstComment)
            {
                ProductCommentModels p = new ProductCommentModels();
                p.content = productComment.Content;
                p.date = productComment.DateCreated;
                p.fullName = UserService.GetByUserID(productComment.CustomerID).FullName;
                lstCommentModels.Add(p);
            }

            return PartialView("Partial/_CommentList", lstCommentModels);
        }

        public ActionResult Search(string keyword)
        {
            ViewBag.keyword = keyword;
            SEOModels seoModels = new SEOModels();
            return View(seoModels);
        }

        public ActionResult SearchList(string keyword, int sortOrder = 0, int? page = 1, string price = "All", string currentFilter = "")
        {
            int pageSize = BDShopConfiguration.Web.pageSize;
            ViewBag.Url = "";
            //Get value for sort ddl
            List<SelectListItem> lstSort = new List<SelectListItem>();
            SelectListItem itemDefault = new SelectListItem() { Text = FO.macdinh, Value = "0", Selected = (0 == sortOrder) ? true : false };
            SelectListItem itemNameAZ = new SelectListItem() { Text = FO.tensanphamaz, Value = "1", Selected = (1 == sortOrder) ? true : false };
            SelectListItem itemNameZA = new SelectListItem() { Text = FO.tensanphamza, Value = "2", Selected = (2 == sortOrder) ? true : false };
            SelectListItem itemPriceTC = new SelectListItem() { Text = FO.giathapcao, Value = "3", Selected = (3 == sortOrder) ? true : false };
            SelectListItem itemPriceCT = new SelectListItem() { Text = FO.giacaothap, Value = "4", Selected = (4 == sortOrder) ? true : false };
            SelectListItem itemRateH = new SelectListItem() { Text = FO.binhchoncaonhat, Value = "5", Selected = (5 == sortOrder) ? true : false };
            SelectListItem itemRateL = new SelectListItem() { Text = FO.binhchonthapnhat, Value = "6", Selected = (6 == sortOrder) ? true : false };
            IEnumerable<SelectListItem> eItem = new SelectListItem[] { itemDefault, itemNameAZ, itemNameZA, itemPriceTC, itemPriceCT, itemRateH, itemRateL };
            lstSort.AddRange(eItem);
            ViewBag.Sort = lstSort;

            ViewBag.page = page;
            ViewBag.sortOrder = sortOrder;
            ViewBag.Price = price;

            List<ProductCacheComplex> lstProduct = new List<ProductCacheComplex>();
            //Get Product 
            lstProduct = ProductCache.Instance.Get().Where(p => p.Name.ToLower().RemoveSign().Contains(TextUtility.RemoveSign4VietnameseString(keyword.ToLower()))).ToList();

            switch (sortOrder)
            {
                case 1:
                    lstProduct = lstProduct.OrderBy(p => p.Name).ToList();
                    break;
                case 2:
                    lstProduct = lstProduct.OrderByDescending(p => p.Name).ToList();
                    break;
                case 3:
                    lstProduct = lstProduct.OrderBy(p => p.Price).ToList();
                    break;
                case 4:
                    lstProduct = lstProduct.OrderByDescending(p => p.Price).ToList();
                    break;
                case 5:
                    lstProduct = lstProduct.OrderByDescending(p => Math.Ceiling((float)p.Rating / p.Rater)).ToList();
                    break;
                case 6:
                    lstProduct = lstProduct.OrderBy(p => Math.Ceiling((float)p.Rating / p.Rater)).ToList();
                    break;
                default:
                    lstProduct = lstProduct.OrderByDescending(p => p.DateCreated).ToList();
                    break;
            }

            //Filter by price
            List<ProductCacheComplex> lstProductResult = new List<ProductCacheComplex>();
            if (price == "All")
            {
                lstProductResult = lstProduct;
            }
            else
            {
                string[] lstPrice = price.Split('-');
                foreach (var s in lstPrice)
                {
                    switch (s)
                    {
                        case "0":
                            lstProductResult = lstProductResult.Union(lstProduct.Where(p => p.Price < 100000)).ToList();
                            break;
                        case "1":
                            lstProductResult = lstProductResult.Union(lstProduct.Where(p => p.Price > 100000 && p.Price <= 500000)).ToList();
                            break;
                        case "2":
                            lstProductResult = lstProductResult.Union(lstProduct.Where(p => p.Price > 500000 && p.Price <= 1000000)).ToList();
                            break;
                        case "3":
                            lstProductResult = lstProductResult.Union(lstProduct.Where(p => p.Price > 1000000)).ToList();
                            break;
                    }
                }
            }

            //Paging
            int pageNumber = (page ?? 1);

            return PartialView("Partial/_SearchList", lstProductResult.ToPagedList(pageNumber, pageSize));
        }

        #region Child Action Only
        [ChildActionOnly]
        [OutputCache(Duration = 3600)]
        public ActionResult FeaturedProduct()
        {
            int featuredCount = int.Parse(ConfigCache.Instance.Get().Where(c => c.Key.ToUpper() == BDShopConfiguration.Key.fc.ToUpper()).First().Value);
            var featuredProduct = ProductCache.Instance.Get().Where(p => p.IsFeatured == true && p.Status == (int)ProductStatus.InStock).Take(featuredCount).ToList<ProductCacheComplex>();
            return PartialView("Partial/_FeaturedProduct", featuredProduct);
        }

        [ChildActionOnly]
        [OutputCache(Duration = 3600)]
        public ActionResult LatestProduct(int flag, long id = 0, int catID = 0, int tagID = 0, int supID = 0, int brandID = 0)
        {
            int latestCount = 0;
            List<ProductCacheComplex> latestProduct = new List<ProductCacheComplex>();
            List<ProductCategory> lstProductOfCat = new List<ProductCategory>();
            List<ProductTag> lstProductOfTag = new List<ProductTag>();
            List<ProductCacheComplex> lstProductOfSupplier = new List<ProductCacheComplex>();
            List<ProductCacheComplex> lstProductOfBrand = new List<ProductCacheComplex>();

            //flag=1: Hien thi san pham moi nhat o tab
            //flag=2: Hien thi san pham moi nhat o trang chi tiet san pham
            switch (flag)
            {
                case 1:
                    latestCount = int.Parse(ConfigCache.Instance.Get().Where(c => c.Key.ToUpper() == BDShopConfiguration.Key.lc.ToUpper()).First().Value);
                    latestProduct = ProductCache.Instance.Get().OrderByDescending(p => p.DateCreated).Take(latestCount).ToList<ProductCacheComplex>();
                    return PartialView("Partial/_LatestProductTab", latestProduct);

                case 2:
                    latestCount = 5;
                    //get category of product
                    List<ProductCategory> lstProductCategory = ProductCategoryCache.Instance.Get().Where(pc => pc.ProductID == id).ToList();
                    //get product of category
                    foreach (var productCategory in lstProductCategory)
                    {
                        lstProductOfCat = lstProductOfCat.Union(ProductCategoryCache.Instance.Get().Where(p => p.CategoryID == productCategory.CategoryID)).ToList();
                    }
                    //Get Product Of Category 
                    latestProduct = lstProductOfCat.Join(ProductCache.Instance.Get(), pc => pc.ProductID, p => p.ID, (pc, p) => p).Distinct().ToList();

                    latestProduct = latestProduct.OrderByDescending(p => p.DateCreated).Take(latestCount).ToList();

                    return PartialView("Partial/_LatestProduct", latestProduct);
                case 3:
                    latestCount = 5;
                    //get product of category
                    lstProductOfCat = ProductCategoryCache.Instance.Get().Where(pc => pc.CategoryID == catID).ToList();
                    //Get Product Of Category 
                    latestProduct = lstProductOfCat.Join(ProductCache.Instance.Get(), pc => pc.ProductID, p => p.ID, (pc, p) => p).Distinct().ToList();

                    latestProduct = latestProduct.OrderByDescending(p => p.DateCreated).Take(latestCount).ToList();

                    return PartialView("Partial/_LatestProduct", latestProduct);
                case 4:
                    latestCount = 5;
                    //get product of tag
                    lstProductOfTag = ProductTagService.GetListProductByTag(tagID);
                    //Get Product Of tag
                    latestProduct = lstProductOfTag.Join(ProductCache.Instance.Get(), pc => pc.ProductID, p => p.ID, (pc, p) => p).Distinct().ToList();

                    latestProduct = latestProduct.OrderByDescending(p => p.DateCreated).Take(latestCount).ToList();

                    return PartialView("Partial/_LatestProduct", latestProduct);
                case 5:
                    latestCount = 5;
                    //get product of supplier
                    lstProductOfSupplier = ProductCache.Instance.Get().Where(p => p.SupplierID == supID).ToList();

                    latestProduct = lstProductOfSupplier.OrderByDescending(p => p.DateCreated).Take(latestCount).ToList();

                    return PartialView("Partial/_LatestProduct", latestProduct);

                case 6:
                    latestCount = 5;
                    //get product of supplier
                    lstProductOfBrand = ProductCache.Instance.Get().Where(p => p.BrandID == brandID).ToList();

                    latestProduct = lstProductOfBrand.OrderByDescending(p => p.DateCreated).Take(latestCount).ToList();

                    return PartialView("Partial/_LatestProduct", latestProduct);
                case 7:
                    latestCount = 5;
                    latestProduct = ProductCache.Instance.Get().OrderByDescending(p => p.DateCreated).Take(latestCount).ToList<ProductCacheComplex>();
                    return PartialView("Partial/_LatestProduct", latestProduct);
            }

            return View();
        }

        [ChildActionOnly]
        [OutputCache(Duration = 3600)]
        public ActionResult BestSellerProduct(int flag, long id = 0)
        {
            int bestSellerCount = 0;
            List<ProductCacheComplex> bestSellerProduct = new List<ProductCacheComplex>();

            //flag=1: Hien thi san pham moi nhat o tab
            //flag=2: Hien thi san pham moi nhat o trang chi tiet san pham
            switch (flag)
            {
                case 1:
                    bestSellerCount = int.Parse(ConfigCache.Instance.Get().Where(c => c.Key.ToUpper() == BDShopConfiguration.Key.bsc.ToUpper()).First().Value);
                    bestSellerProduct = ProductCache.Instance.Get().OrderByDescending(p => p.SellTotal).Take(bestSellerCount).ToList<ProductCacheComplex>();
                    return PartialView("Partial/_BestSellerTab", bestSellerProduct);
                case 2:
                    bestSellerCount = 5;
                    List<ProductCategory> lstProductOfCat = new List<ProductCategory>();
                    //get category of product
                    List<ProductCategory> lstProductCategory = ProductCategoryCache.Instance.Get().Where(pc => pc.ProductID == id).ToList();
                    //get product of category
                    foreach (var productCategory in lstProductCategory)
                    {
                        lstProductOfCat = lstProductOfCat.Union(ProductCategoryCache.Instance.Get().Where(p => p.CategoryID == productCategory.CategoryID)).ToList();
                    }
                    //Get Product Of Category 
                    bestSellerProduct = lstProductOfCat.Join(ProductCache.Instance.Get(), pc => pc.ProductID, p => p.ID, (pc, p) => p).Distinct().ToList();

                    bestSellerProduct = bestSellerProduct.OrderByDescending(p => p.SellTotal).Take(bestSellerCount).ToList();

                    return PartialView("Partial/_BestSellerProduct", bestSellerProduct);
            }
            return View();
        }

        [ChildActionOnly]
        [OutputCache(Duration = 3600)]
        public ActionResult BestViewProduct()
        {
            int bestViewCount = int.Parse(ConfigCache.Instance.Get().Where(c => c.Key.ToUpper() == BDShopConfiguration.Key.bsc.ToUpper()).First().Value);
            var bestViewProduct = ProductCache.Instance.Get().OrderByDescending(p => p.ViewTotal).Take(bestViewCount).ToList<ProductCacheComplex>();

            return PartialView("Partial/_BestViewTab", bestViewProduct);

        }

        [ChildActionOnly]
        [OutputCache(Duration = 3600)]
        public ActionResult RelatedProduct(long id)
        {
            int relatedCount = int.Parse(ConfigCache.Instance.Get().Where(c => c.Key.ToUpper() == BDShopConfiguration.Key.rc.ToUpper()).First().Value);
            var relatedProduct = ProductRelatedService.GetByID(id).Take(relatedCount).ToList();
            List<ProductCacheComplex> lstRelatedProduct = relatedProduct.Join(ProductCache.Instance.Get(), rp => rp.ProductRelatedID, p => p.ID, (rp, p) => p).ToList();

            return PartialView("Partial/_RelatedProduct", lstRelatedProduct);

        }

        #endregion
    }
}
